iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
佛心分享-刷題不只是刷題

圖解LeetCode(入門篇)系列 第 2

圖解LeetCode(入門篇): 9. Palindrome Number

  • 分享至 

  • xImage
  •  

9. Palindrome Number

題目描述:

給定一個整數 x,如果 x 是一個回文數,則返回 true;否則返回 false

回文數是指無論是正序(從左到右)還是倒序(從右到左)讀取時,結果都是相同的整數。例如,121 是回文數,而 123 則不是。
Example 1:

  • Input: x = 121
  • Output: true
  • Explanation: 121 從左到右和從右到左讀取的結果都是 121,因此它是一個回文數。

Example 2:

  • Input: x = -121
  • Output: false
  • Explanation: 從左到右讀取時為 -121,從右到左讀取則為 121-。因此,它不是一個回文數。

Example 3:

  • Input: x = 10
  • Output: false
  • Explanation: 從右到左讀取時為 01。因此,它不是一個回文數。

解題思路:
這道題目主要考驗的是解題者是否能夠將一個數字逐位拆解,並且正確地處理進位操作。通過逐位比較數字的左右兩側,我們可以判斷該數字是否為回文數。這不僅需要考慮數字的基本操作,還需要解題者靈活運用數學技巧來實現這一過程。
在十進制中,逐位拆解數字需要使用取餘數的操作,即 x % 10。而進位操作則是將數字除以十後取整數部分,即 Math.floor(x / 10)。當我們逐位拆解數字時,拆解完的位數需要存儲在另一個變數中(例如 revertedNumber)。需要注意的是,每次儲存前,都必須將前一次的結果進位(乘以 10)後再將當前位數相加。這樣才能確保數字逐位拆解並且正確重組。當 revertedNumber 大於原本的 x 時,就可以停止while迴圈的操作並比較結果。此時,例如 x = 1revertedNumber = 12,由於中位數不影響回文(因為它總是與自己相等),我們可以簡單地將 revertedNumber 除以 10 去除中位數,再與 x 進行比較。如果兩者相等,則該數字是回文數。
https://ithelp.ithome.com.tw/upload/images/20240811/20168306AoeF2x7lwg.jpg
此外,從 Example 2 和 Example 3 可以看出,負數以及尾數為 0 的數字都不會是回文數。唯一的例外是數字 0,因為它只有一個位數,所以是回文數。基於這些觀察,我們可以在開始時先排除不可能是回文數的情況,這樣就可以更高效地進行後續的 while 迴圈判斷和處理。

var isPalindrome = function(x) {
    if(x < 0) return false;
    if(x == 0) return true;
    if(x % 10 == 0) return false;

    let revertedNumber = 0;
    while (x > revertedNumber) {
        revertedNumber = revertedNumber * 10 + x % 10;
        x = Math.floor(x / 10);
    }

    return x === revertedNumber || x === Math.floor(revertedNumber / 10);
};

時間複雜度: O(log n),因為在每次 while 迴圈中,我們將輸入數字 x 除以 10。最壞情況下,迴圈會執行 n 個位數的一半次數,即大約是 log(n) 次。
空間複雜度: O(1),因為我們只使用了常數空間來存儲幾個變數,不需要額外的陣列或其他數據結構。這意味著無論 x 的大小如何,所需的額外空間都是固定的。

除了上述的解法之外,對於熟悉 JavaScript 的讀者來說,應該能想到一種更簡便且直觀的解法。這裡我們稍微討論一下這個解法,但由於它依賴於 JavaScript 本身提供的 API,不一定適用於其他語言,因此僅供參考。

在 JavaScript 中,我們可以通過以下步驟快速檢查一個數字是否為回文數:

首先,將數字轉換為字串(string),使用 x.toString() 方法。
然後,將該字串轉換為陣列(Array),以便能夠使用陣列的操作方法。這一步使用 str.split(''),將字串分割成單個字符的陣列。
接著,對該陣列進行反轉操作,使用 reverse() 方法來反轉陣列中的元素順序。
最後,將反轉後的陣列重新轉回字串,使用 join('') 方法將陣列中的元素連接成一個字串,然後將其與原始字串進行比較。

這種方法非常簡單,且對於熟悉 JavaScript API 的開發者來說非常直觀。然而,這種解法的效率會略低於上面的數學方法,因為它涉及多次字串和陣列的轉換操作,不過在大多數情況下仍然能夠快速解決問題。
https://ithelp.ithome.com.tw/upload/images/20240811/20168306Olkq8LjNf2.jpg

var isPalindrome = function(x) {
    if (x < 0) {
        return false;
    }

    const str = x.toString();
    const reversedStr = str.split('').reverse().join('');
    
    return str === reversedStr;
};

時間複雜度: O(n),其中 n 是整數 x 轉換為字串後的長度。字串的反轉和比較操作的時間複雜度都是 O(n),因為這些操作需要遍歷整個字串。
空間複雜度: O(n),因為我們需要額外的空間來存儲字串的反轉結果。在進行反轉操作時,會創建一個新陣列來保存反轉後的字串,這就佔用了額外的記憶體空間。因此,整個過程的空間複雜度與字串的長度成正比。

總結:
透過這道題目,LeetCode 教會我們如何對數字進行拆解和重組,而這個技巧在後續的題目中會反復出現,可見其重要性。此外,現代程式語言通常提供豐富的 API,這些 API 不僅在解 LeetCode 時有用,在日常工作中也能加速我們的工作流程。只要在不顯著犧牲時間和空間複雜度的情況下,利用 API 來解題也是一種有效的解題思路。

對於這道題,我們可以將其歸類為「while 迴圈」和「array.reverse」這兩個分類。這樣的分類方式有助於我們在日後回顧時,更清晰地理解不同解法所涉及的核心概念和技巧。


上一篇
圖解LeetCode(入門篇): 1. Two Sum
下一篇
圖解LeetCode(入門篇): 13. Roman to Integer
系列文
圖解LeetCode(入門篇)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言